package btservice;

import java.awt.Toolkit;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;

import javax.bluetooth.LocalDevice;
import javax.bluetooth.UUID;
import javax.microedition.io.Connector;
import javax.microedition.io.StreamConnection;
import javax.microedition.io.StreamConnectionNotifier;

public class BTService implements Runnable {
    
    // input from client
    private BufferedReader reader;
    // output to client
    private PrintStream printer;
    private boolean run = true;		
    private DataStorage dataStorage = DataStorage.getInstance();
    private StreamConnectionNotifier service = null;
    private StreamConnection conn = null;
    public void run() {

        try {
            
            serveForever();
            
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
    
    public void serveForever() throws IOException {
        while(true) {
            startService();
        }
    }
    
    /**
     * Starts the service and serves it till the client disconnects
     */
    private void startService() throws IOException {
        
        // define the uuid and service url
    	
    	try{
        LocalDevice local = LocalDevice.getLocalDevice();
        UUID uuid = new UUID("83a84742607046b09ab7d27531da2197", false);
        String url = "btspp://localhost:" + uuid.toString()
                + ";name=CarAppBtService";

        log("Service url: " + url);
        log("service address: " + local.getBluetoothAddress());
        
        // open the connection
        service = (StreamConnectionNotifier) Connector
                .open("btspp://localhost:" + uuid.toString()
                        + ";name=helloService");

        log("Waiting for connection");
        
        // accept client connections
        conn = (StreamConnection) service.acceptAndOpen();
        Toolkit.getDefaultToolkit().beep();  
        log("Connection established");
        
        // wrap stream in a reader
        InputStreamReader inputReader = new InputStreamReader(
                conn.openInputStream());

        reader = new BufferedReader(inputReader);
        printer = new PrintStream(conn.openOutputStream());
        
        // listen forever
        while (run) {
        	
            String in = read();
            log("Received: " + in);
            
            // null means that the client has disconnected
            if (in == null) {
                // stop running
                run = false;
            } else {
                // process the command otherwise
                process(in);
            }
        }

        log("Connection lost");
    	}catch(Exception ex){
    		log(ex.getMessage());
    	}finally{
            reader.close();
            printer.close();
            conn.close();
            conn = null;
            service.close();
            service = null;
    	}
        // close the streams
        

    }
    
    /**
     * Processes the given message
     * @param message
     */
    private void process(String message) {
    	System.out.println("DEBUG: lights: " + DataStorage.getInstance().getDataSets().get("isLightsOn") + DataStorage.getInstance().getDataSets().get("isLocked"));
    	switch(message)
    	{
    	case ServiceCommands.DOORS_LOCK:
    		dataStorage.getDataSets().put("isLocked", "true");
    		write("doors:"+dataStorage.getDataSets().get("isLocked")+"\n");
    		
    		break;
    	case ServiceCommands.DOORS_UNLOCK:
    		dataStorage.getDataSets().put("isLocked", "false");
    		write("doors:"+dataStorage.getDataSets().get("isLocked")+"\n");
    		
    		break;
    	case ServiceCommands.IS_LOCKED:
    		write("doors:"+dataStorage.getDataSets().get("isLocked")+"\n");
    		break;
    	case ServiceCommands.LIGHTS_ON:
    	    dataStorage.getDataSets().put("isLightsOn", "true");
    		write("light:" +dataStorage.getDataSets().get("isLightsOn")+"\n");
    		
    		break;
    	case ServiceCommands.LIGHTS_OFF:
    		dataStorage.getDataSets().put("isLightsOn", "false");
    		write("light:" +dataStorage.getDataSets().get("isLightsOn")+"\n");
    		
    		break;
    	case ServiceCommands.IS_LIGHTS_ON:
    		write("light:" +dataStorage.getDataSets().get("isLightsOn")+"\n");
    		break;
    	default :
    		write("Command not recognized\n");
    		break;
  		
    	}
        // todo: implement handling of messages
    }
    
    /**
     * Logs an event
     * @param message
     */
    private void log(String message) {
        System.out.println(message);
    }
    
    /**
     * Reads input from the connected client
     * @return read input
     * @throws IOException
     */
    private String read() throws IOException {
        return reader.readLine();
    }
    
    /**
     * Writes message to the connected client
     * @param message
     */
    private void write(String message) {
        printer.print(message);
        printer.flush();
        log("Sent: " + message);
    }
    
    public void diminishOil()
    {
    	dataStorage.getDataSets().put("oilStatus","10");
    	if(getOilStatus())
        {
    	    write(ServiceCommands.OIL_IS_LOW + "\n");
        }
    }
    public void refillOil()
    {
    	dataStorage.getDataSets().put("oilStatus","100");
    	if(!getOilStatus())
        {
    	    write(ServiceCommands.REFILL_OIL + "\n");
        }
    }    
    
    public boolean getOilStatus()
    {
    	int oilStatus = Integer.parseInt(dataStorage.getDataSets().get("oilStatus"));
    	boolean oilIsLow;
    	
    	if(oilStatus < 15)
    	{
    		
    		oilIsLow = true;
    	}else{
    		oilIsLow=false;
    	}
    	return oilIsLow;
    }

}
